package com.e3.core.base;

import java.io.Serializable;
import java.math.BigInteger;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.HibernateTemplate;

import com.e3.core.lang.DataType;
import com.e3.web.core.model.SuperModel;

public class SuperDAO extends AbstractSuperService {

	private HibernateTemplate hibTemplate;
	
	private String[] comFields = {"create_user_id","create_time","modify_user_id","modify_time"};

	public HibernateTemplate getHibTemplate() {
		return hibTemplate;
	}

	public void setHibTemplate(HibernateTemplate hibTemplate) {
		this.hibTemplate = hibTemplate;
	}

	public void persist(SuperEntity entity) {
		getHibTemplate().persist(entity);
	}

	public <T extends SuperEntity> T loadById(Class<T> entityClass, Serializable id) {
		return getHibTemplate().load(entityClass, id);
	}

	public <T extends SuperEntity> T getById(Class<T> entityClass, Serializable id) {
		return getHibTemplate().get(entityClass, id);
	}

	@SuppressWarnings("unchecked")
	public <T extends SuperEntity> List<T> find(String queryString) {
		return getHibTemplate().find(queryString);
	}

	@SuppressWarnings("unchecked")
	public <T extends SuperEntity> List<T> find(String queryString, String value) {
		return getHibTemplate().find(queryString, value);
	}
	
	@SuppressWarnings("rawtypes")
	public List find(String queryString,Object value){
		return getHibTemplate().find(queryString, value);
	}

	public <T extends SuperEntity> List<T> findBySingleField(Class<T> entityClass, String fieldName, String... values) {
		return findBySingleField(entityClass, fieldName, DataType.STRING, values);
	}
	
	public <T extends SuperEntity> List<T> findBySingleField(Class<T> entityClass, String fieldName, Long... values) {
		return findBySingleField(entityClass, fieldName, DataType.LONG, values);
	}
	
	

	@SuppressWarnings("unchecked")
	public <T extends SuperEntity> List<T> findBySingleField(Class<T> entityClass, String fieldName, int fieldType, Serializable... values) {
		String entityName = entityClass.getSimpleName();
		StringBuffer sql = new StringBuffer();
		sql.append("SELECT entity FROM " + entityName + " entity ");

		String whSQL = getWhereSQL(fieldName, fieldType, values);
		sql.append(whSQL);

		return getHibTemplate().find(sql.toString());
	}

	@SuppressWarnings("unchecked")
	public <T extends SuperEntity> List<T> findByNamedParams(String queryString, String paramName, Object value) {
		return getHibTemplate().findByNamedParam(queryString, paramName, value);
	}

	@SuppressWarnings("unchecked")
	public <T extends SuperEntity> List<T> findByNamedParams(String queryString, String[] paraNames, Object[] values) {
		return getHibTemplate().findByNamedParam(queryString, paraNames, values);
	}

	public void merge(SuperEntity entity) {
		getHibTemplate().merge(entity);
	}

	public void delete(SuperEntity entity) {
		getHibTemplate().delete(entity);
	}

	public <T extends SuperEntity> void deleteAllBySingleField(Class<T> entityClass, String fieldName, String... values) {
		deleteAllBySingleField(entityClass, fieldName, DataType.STRING, values);
	}
	
	public <T extends SuperEntity> void deleteAllBySingleField(Class<T> entityClass, String fieldName, Long... values) {
		deleteAllBySingleField(entityClass, fieldName, DataType.LONG, values);
	}

	public <T extends SuperEntity> void deleteAllBySingleField(Class<T> entityClass, String fieldName, int fieldType,
			Serializable... values) {
		String entityName = entityClass.getSimpleName();
		StringBuffer sql = new StringBuffer();
		sql.append("DELETE FROM " + entityName + " entity ");

		String whSQL = getWhereSQL(fieldName, fieldType, values);
		sql.append(whSQL);

		getHibTemplate().bulkUpdate(sql.toString());

	}

	protected String getWhereSQL(String fieldName, int fieldType, Serializable... values) {
		StringBuffer whSQL = new StringBuffer();
		if (values != null && values.length > 0) {
			whSQL.append(" WHERE ");
			for (int i = 0; i < values.length; i++) {
				Serializable id = values[i];
				Object value = getFieldValueByType(id, fieldType);
				whSQL.append("entity." + fieldName + "=" + value);
				if (i < values.length - 1) {
					whSQL.append(" OR ");
				}
			}
		}
		return whSQL.toString();
	}

	protected Object getFieldValueByType(Object value, int type) {
		if (type == DataType.STRING) {
			return "'" + value + "'";
		}

		return value;
	}

	public long counter(final String counterSQL) {
		@SuppressWarnings("rawtypes")
		List list = getHibTemplate().executeWithNativeSession(new HibernateCallback<List>() {

			public List doInHibernate(Session session) throws HibernateException {
				Query queryObject = session.createQuery(counterSQL);
				return queryObject.list();
			}
		});
		Object obj = (list == null || list.isEmpty()) ? null : list.get(0);
		return obj == null ? 0 : (Long) obj;
	}
	
	@SuppressWarnings("rawtypes")
	public long counter(String queryString,Object value){
		List list = getHibTemplate().find(queryString, value);
		Object obj = (list == null || list.isEmpty()) ? null : list.get(0);
		return obj == null ? 0 : (Long) obj;

	}
	
	@SuppressWarnings("rawtypes")
	public List executeNativeQueryByNameParams(final String queryString,final Map<String,Object> paras){
		List list = getHibTemplate().executeWithNativeSession(new HibernateCallback<List>() {
			public List doInHibernate(Session session) throws HibernateException {
				Query queryObject = session.createSQLQuery(queryString);
				if(paras!=null){
					Iterator<String> it = paras.keySet().iterator();
					while(it.hasNext()){
						String pName = it.next();
						Object value = paras.get(pName);
						queryObject.setParameter(pName, value);
					}
				}
				
				return queryObject.list();
			}
		});
		return list;
	}
	
	@SuppressWarnings("rawtypes")
	public List executeNativeQuery(final String queryString,final Object[] paras){
		List list = getHibTemplate().executeWithNativeSession(new HibernateCallback<List>() {
			public List doInHibernate(Session session) throws HibernateException {
				Query queryObject = session.createSQLQuery(queryString);
				if(paras!=null&&paras.length>0){
					for(int i=0;i<paras.length;i++){
						queryObject.setParameter(i, paras[i]);
					}
				}
				
				return queryObject.list();
			}
		});
		return list;
	}
	
	@SuppressWarnings("rawtypes")
	public List executeHQLQuery(final String queryString,final Object[] paras){
		List list = getHibTemplate().executeWithNativeSession(new HibernateCallback<List>() {
			public List doInHibernate(Session session) throws HibernateException {
				Query queryObject = session.createQuery(queryString);
				if(paras!=null&&paras.length>0){
					for(int i=0;i<paras.length;i++){
						queryObject.setParameter(i, paras[i]);
					}
				}
				return queryObject.list();
			}
		});
		return list;
	}
	
	@SuppressWarnings("rawtypes")
	public List executePagingHQLQuery(final String queryString,final Object[] paras,final int start,final int max){
		List list = getHibTemplate().executeWithNativeSession(new HibernateCallback<List>() {
			public List doInHibernate(Session session) throws HibernateException {
				Query queryObject = session.createQuery(queryString);
				queryObject.setFirstResult(start);
				queryObject.setMaxResults(max);
				if(paras!=null&&paras.length>0){
					for(int i=0;i<paras.length;i++){
						queryObject.setParameter(i, paras[i]);
					}
				}
				return queryObject.list();
			}
		});
		return list;
	}

	protected String getComFieldsSelect(String prefix){
		String p = prefix;
		if(p!=null&&p.length()>0){
			p = p+".";
		}
		 StringBuffer select = new StringBuffer();
		 int length = comFields.length;
		 for (int i=0;i<length;i++) {
			if(i<length-1){
				select.append(p+comFields[i]+",");
			}
			else if(i == length-1){
				select.append(p+comFields[i]);
			}
		}
		 return select.toString();
	}
	
	protected <T extends SuperModel> T fetchComFieldsToModel(List<?> result,T model){
		if(result==null||result.isEmpty()){
			return model;
		}
		int length = comFields.length;
		if(result.size()< length){
			System.err.println("the result size "+result.size()+" < "+ length +" of the common fields size ");
			return model;
		}
		
		BigInteger modifyTime = (BigInteger)result.get(length-1);
		if(modifyTime != null){
			long mt = modifyTime.longValue();
			Date date = new Date(mt);
			model.setModifyTime(date);
		}
		
		BigInteger modifyUID = (BigInteger)result.get(length-2);
		if(modifyUID != null){
			model.setModifyUserId(modifyUID.longValue());
		}
		
		BigInteger createTime = (BigInteger)result.get(length-3);
		if(createTime != null){
			long mt = createTime.longValue();
			Date date = new Date(mt);
			model.setCreateTime(date);
		}
		
		BigInteger createUID = (BigInteger)result.get(length-4);
		if(createUID != null){
			model.setModifyUserId(createUID.longValue());
		}
		
		return model;
	}
}
